﻿using System;
using System.Collections;
using System.Threading;
using System.Web;
using System.Collections.Generic;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Portals;
using DotNetNuke.Entities.Host;
using DotNetNuke.Services.Mail;
using DotNetNuke;
using System.IO;
using DotNetNuke.Common;
using Microsoft.ApplicationBlocks.Data;
namespace Spiffy.DatabaseMonitor
{
    public class Monitor : IHttpModule
    {

        #region Variables
        private string errorActivatedFile = HttpRuntime.AppDomainAppPath + "errorActivated.resources";
        #endregion

        #region IHttpModule Members

        public void Dispose() { }

        public void Init(HttpApplication context)
        {

            context.BeginRequest += new EventHandler(OnBeginRequest);
        }


        public void OnBeginRequest(Object source, EventArgs e)
        {
            try
            {
                HttpApplication app = source as HttpApplication;
                if (app != null)
                {

                    if (app.Request.Url.ToString().ToLower().Contains(".aspx") || 
                        app.Request.Url.ToString().EndsWith(app.Request.Url.Host + app.Request.Url.AbsolutePath) ||
                        app.Request.Url.ToString().EndsWith(app.Request.Url.Host + app.Request.Url.AbsolutePath.Substring(0,app.Request.Url.AbsolutePath.Length-1))
                        )
                    {

                        CheckThreadStatus();
                        if (InitialStatus() && Globals.Status != Globals.UpgradeStatus.Install)
                        {
                            if (!isRunning)
                            {

                                isRunning = true;

                                ModuleController mc = new ModuleController();
                                PortalController pc = new PortalController();
                                ArrayList portals = pc.GetPortals();
                                ModuleInfo mInfo = null;

                                if (portals != null)
                                {
                                    foreach (PortalInfo p in portals)
                                    {
                                        ArrayList modules = mc.GetModulesByDefinition(p.PortalID, "Spiffy: Database Monitor");
                                        if (modules.Count > 0)
                                        {
                                            ModuleInfo tmpModInfo = modules[0] as ModuleInfo;

                                            if (tmpModInfo.IsDeleted == false)
                                            {
                                                mInfo = tmpModInfo;
                                                break;
                                            }

                                        }

                                    }



                                    if (mInfo != null)
                                    {

                                        Hashtable modSettings = mc.GetModuleSettings(mInfo.ModuleID);
                                        if (modSettings["SendEmail"] != null)
                                        {
                                            SendEmail = Convert.ToBoolean(modSettings["SendEmail"]);
                                        }
                                        if (modSettings["RetryTimer"] != null)
                                        {
                                            RetryTimer = Convert.ToInt32(modSettings["RetryTimer"]);
                                        }

                                    }


                                    HostEmail = Host.HostEmail;
                                    HostTitle = Host.HostTitle;
                                    Thread thd = new Thread(new ThreadStart(backgroundWorker1_DoWork));
                                    MonitorThreads.Add(thd);
                                    thd.Name = "Database Monitor";
                                    thd.IsBackground = true;
                                    thd.Start();
                                }
                            }
                        }
                        else
                        {
                            RunError();
                        }
                    }
                }

                
                
            }
            catch (Exception ex)
            {
                isRunning = false;
                foreach (Thread t in MonitorThreads)
                {
                    t.Abort();
                }

            }
        }

        private bool InitialStatus()
        {
            ConnStr = Config.GetConnectionString();
            try
            {
                SqlHelper.ExecuteScalar(ConnStr, System.Data.CommandType.Text, "select 'Database Monitor Pulse'");
                
            }
            catch (Exception ex)
            {
                if (!isInError)
                {
                    RunError();
                    return false;
                }

            }

            try
            {
                if (File.Exists(errorActivatedFile))
                {
                    File.Delete(errorActivatedFile);
                }
            }
            catch(Exception ex) 
            {

            }

            

            return true;
        }


        private void CheckThreadStatus()
        {
            bool checkAliveStatus = false;
            for (int i = 0; i < MonitorThreads.Count; i++)
            {
                if (MonitorThreads[i].IsAlive)
                {
                    checkAliveStatus = true;
                }
                else
                {
                    MonitorThreads.RemoveAt(i);
                }
            }
            if (!checkAliveStatus)
            {
                isRunning = false;
            }
        }

        public void RunError()
        {
            isInError = true;
            if (SendEmail)
            {

                if (!File.Exists(errorActivatedFile))
                {
                    SendEmailAlert();
                    try
                    {
                        FileStream errorFile = File.Create(errorActivatedFile);
                        errorFile.Close();
                    }
                    catch (Exception ex) { }
                   
                }
            }
            
            Config.Touch();          

        }

        public void SendEmailAlert()
        {
            if (HostEmail != "")
            {
                Mail.SendMail(HostEmail, HostEmail, "", HostTitle + " is restarting", "", "", "", "", "", "", "");
            }
            
        }

        #endregion

        #region Background Threads
        private void backgroundWorker1_DoWork()
        {
            while (!isInError)
            {

                try
                {
                    SqlHelper.ExecuteScalar(ConnStr, System.Data.CommandType.Text, "select 'Database Monitor Pulse'");
                }
                catch (Exception ex)
                {
                    if (!isInError)
                    {
                        RunError();
                        break;
                    }

                }

                System.Threading.Thread.Sleep(RetryTimer);
            }
        }

        #endregion

        #region Variables
            private static bool _isRunning = false;
            private static bool _isInError = false;
            private static string _connStr = "";
            private static string _hostEmail = "";
            private static string _hostTitle = "";
            private static bool _sendEmail = true;
            private static int _retryTimer = 15000;
            private static List<Thread> MonitorThreads = new List<Thread>();
        #endregion

        #region Properties
            public static bool isRunning
            {
                get { return _isRunning; }
                set { _isRunning = value; }
            }
            public static bool isInError
            {
                get { return _isInError; }
                set { _isInError = value; }
            }
            public static string ConnStr
            {
                get { return _connStr; }
                set { _connStr = value; }

            }
            public static string HostEmail
            {
                get { return _hostEmail; }
                set { _hostEmail = value; }
            }
            public static string HostTitle
            {
                get { return _hostTitle; }
                set { _hostTitle = value; }
            }
            public static bool SendEmail {
                get { return _sendEmail; }
                set {_sendEmail=value; }
            }
            public static int RetryTimer {
                get { return _retryTimer; }
                set { _retryTimer = value; }
            }
        #endregion
    }
}
